// Copyright (c) 1996-2002 John Lyon-Smith. All rights reserved.

#pragma once

#include <wxtl\base.h>

namespace wxtl
{
	class FileMap 
	{
	public:
		FileMap()
		{
			m_handle = NULL;
			m_ptr = NULL;
		}
		virtual ~FileMap()
		{
			close();
		}

		bool isValid() { return m_ptr != NULL; }

		void close()
		{
			if (m_ptr)
			{
				UnmapViewOfFile(m_ptr);
				m_ptr = NULL;
			}

			if (m_handle)
			{
				CloseHandle(m_handle);
				m_handle = NULL;
			}
		}

		// Create a memory mapped file from an existing disk file
		bool create(
			HANDLE hFile, 
			bool *pbOpened = NULL, 
			const TCHAR* szName = NULL, 
			DWORD dwDesiredAccess = FILE_MAP_READ | FILE_MAP_WRITE)
		{
			_ASSERTE(hFile != INVALID_HANDLE_VALUE);
			
			m_handle = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, szName);

			if (m_handle == NULL)
				return false;

			DWORD dw = GetLastError();

			m_ptr = (BYTE*)MapViewOfFile(m_handle, dwDesiredAccess, 0, 0, 0);

			if (m_ptr == NULL)
			{
				close();
				return false;
			}
				
			if (pbOpened != NULL)
			{
				*pbOpened = (dw == ERROR_ALREADY_EXISTS);
			}
				
			return true;
		}

		// Create a memory mapped file from the page file
		bool create(ULONGLONG ullSize,
			bool *pbOpened = NULL, 
			const TCHAR* szName = NULL, 
			DWORD dwDesiredAccess = FILE_MAP_READ | FILE_MAP_WRITE)
		{
			m_handle = CreateFileMapping(
				INVALID_HANDLE_VALUE,
				NULL,
				PAGE_READWRITE,
				DWORD((ullSize >> 32) & 0xFFFFFFFF),
				DWORD(ullSize & 0xFFFFFFFF),
				szName);

			if (m_handle == NULL)
				return false;

			DWORD dw = GetLastError();

			m_ptr = (BYTE*)MapViewOfFile(m_handle, dwDesiredAccess, 0, 0, 0);

			if (m_ptr == NULL)
			{
				close();
				return false;
			}
			
			if (pbOpened != NULL)
			{
				*pbOpened = (dw == ERROR_ALREADY_EXISTS);
			}
				
			return true;
		}

		// Open an existing memory mapped file
		bool open(const TCHAR* szName, 
			DWORD dwDesiredAccess = FILE_MAP_READ | FILE_MAP_WRITE)
		{
			m_handle = OpenFileMapping(dwDesiredAccess, FALSE, szName);

			if (m_handle == NULL)
				return false;

			m_ptr = (BYTE*)MapViewOfFile(m_handle, dwDesiredAccess, 0, 0, 0);

			if (m_ptr == NULL)
			{
				close();
				return false;
			}
				
			return true;
		}

		BYTE* data() { return m_ptr; }
		operator BYTE*() { return data(); } 

	protected:
		HANDLE m_handle;
		BYTE* m_ptr;
	};
}

